using Circus.CodeEditor;
using Circus.CodeEditor.TextSource;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Printing;
namespace Circus.CodeEditor
{
	[DesignTimeVisible(false), ToolboxItem(false)]
	public class EditorPrintDocument : PrintDocument
	{
		private Printing printing;
		private bool startPrinting;
		private int page;
		private int pages;
		private int pageIndex;
		private int pageCount;
		private int startLine;
		protected CodeEditor syntaxEdit;
		private Rectangle GetMarginRect(Rectangle rect)
		{
			Size caps = this.syntaxEdit.Size;
			return new Rectangle(new Point(rect.Left * caps.Width / 100, rect.Top * caps.Height / 100), new Size(rect.Width * caps.Width / 100, rect.Height * caps.Height / 100));
		}
		private int GetPagesCount()
		{
			PageSettings defaultPageSettings = base.PrinterSettings.DefaultPageSettings;
			Rectangle rect = new Rectangle(0, 0, defaultPageSettings.PaperSize.Width - defaultPageSettings.Margins.Left - defaultPageSettings.Margins.Right, defaultPageSettings.PaperSize.Height - defaultPageSettings.Margins.Top - defaultPageSettings.Margins.Bottom);
			int num;
			return this.GetPagesCount(rect, out num);
		}
		protected virtual int GetPagesCount(Rectangle rect, out int linesPerPage)
		{
			this.syntaxEdit.Bounds = rect;
			this.syntaxEdit.DisplayLines.Loaded = true;
			int num = this.syntaxEdit.DisplayLines.DisplayCount - 1;
			linesPerPage = Math.Max(this.syntaxEdit.LinesInHeight, 1);
			this.pages = num / linesPerPage;
			if (num % linesPerPage != 0)
			{
				this.pages++;
			}
			return this.pages;
		}
		protected override void OnBeginPrint(PrintEventArgs e)
		{
			base.OnBeginPrint(e);
			this.startPrinting = true;
			this.page = 0;
			this.pageIndex = 0;
			this.startLine = 0;
		}
		protected virtual void NextPage(ref int startLine)
		{
			startLine += Math.Max(this.syntaxEdit.LinesInHeight, 1);
		}
		protected virtual Rectangle GetPageRect(int startLine, Rectangle rect)
		{
			return rect;
		}
		protected virtual void CreatePrintEdit(CodeEditor edit)
		{
			this.syntaxEdit = this.printing.OnCreatePrintEdit();
			if ((this.printing.Options & PrintOptions.PrintSelection) != PrintOptions.None && !edit.Selection.IsEmpty)
			{
				this.syntaxEdit.Lexer = edit.Lexer;
				this.syntaxEdit.Lines.SetTextAndData(edit.Selection.SelectedText, edit.Source.NeedParse() ? edit.Selection.SelectedColorData : null);
			}
			else
			{
				this.syntaxEdit.Source = edit.Source;
			}
			this.syntaxEdit.BorderStyle = EditBorderStyle.None;
			this.syntaxEdit.Font = edit.Font;
			this.syntaxEdit.WordWrap = ((this.printing.Options & PrintOptions.WordWrap) != PrintOptions.None);
			this.syntaxEdit.Transparent = true;
			this.syntaxEdit.LineSpace = edit.LineSpace;
			this.syntaxEdit.LineSeparator = edit.LineSeparator;
			this.syntaxEdit.Outlining.Assign(edit.Outlining);
			List<Range> list = new List<Range>();
			edit.DisplayLines.GetOutlineRanges(list);
			this.syntaxEdit.DisplayLines.SetOutlineRanges(list);
			
			this.syntaxEdit.Gutter.Visible = false;
			this.syntaxEdit.Gutter.Options = (((this.printing.Options & PrintOptions.LineNumbers) != PrintOptions.None) ? GutterOptions.PaintLineNumbers : GutterOptions.None);
			this.syntaxEdit.Gutter.LineNumbersBackColor = this.syntaxEdit.BackColor;
			if ((this.printing.Options & PrintOptions.PrintSelection) != PrintOptions.None && !edit.Selection.IsEmpty)
			{
				this.syntaxEdit.Gutter.LineNumbersStart += edit.Selection.SelectionRect.Top;
			}
			this.syntaxEdit.EditMargin.Visible = false;
			this.syntaxEdit.Braces.BracesOptions = BracesOptions.None;
			if ((this.printing.Options & PrintOptions.UseSyntax) == PrintOptions.None)
			{
				this.syntaxEdit.SyntaxPaint.DisableSyntaxPaint = true;
			}
			if ((this.printing.Options & PrintOptions.UseColors) == PrintOptions.None)
			{
				this.syntaxEdit.SyntaxPaint.DisableColorPaint = true;
				this.syntaxEdit.Gutter.LineNumbersForeColor = this.syntaxEdit.ForeColor;
			}
			this.syntaxEdit.Scrolling.WindowOriginX = 0;
			this.syntaxEdit.Scrolling.WindowOriginY = 0;
		}
		protected override void OnEndPrint(PrintEventArgs e)
		{
			this.printing.OnFinalized();
			base.OnEndPrint(e);
		}
		protected override void OnPrintPage(PrintPageEventArgs e)
		{
			base.OnPrintPage(e);
			Rectangle marginRect = this.GetMarginRect(e.MarginBounds);
			if (this.startPrinting)
			{
				int num = 0;
				this.pages = this.GetPagesCount(marginRect, out num);
				this.pageCount = Math.Max(this.pages, 1);
				if (base.PrinterSettings.PrintRange == PrintRange.SomePages)
				{
					this.pages = Math.Min(this.pages, base.PrinterSettings.ToPage - base.PrinterSettings.FromPage + 1);
					this.pageIndex = base.PrinterSettings.FromPage - 1;
					this.startLine += num * this.pageIndex;
				}
				this.pages = Math.Max(this.pages, 1);
				this.startPrinting = false;
			}
			Rectangle pageRect = this.GetPageRect(this.startLine, marginRect);
			int lineHeight = this.syntaxEdit.Painter.lineHeight;
			if (lineHeight != 0)
			{
				pageRect.Height = pageRect.Height / lineHeight * lineHeight;
			}
			float scaleX = e.Graphics.DpiX / 100f;
			float scaleY = e.Graphics.DpiY / 100f;
			Painter painter = this.syntaxEdit.Painter;
			painter.BeginPaint(e.Graphics);
			try
			{
				painter.Transform(0, 0, scaleX, scaleY);
				try
				{
				
				}
				finally
				{
					painter.EndTransform();
				}
				this.syntaxEdit.SyntaxPaint.PaintWindow(painter, this.startLine, new Rectangle(new Point(0, 0), pageRect.Size), marginRect.Location, scaleX, scaleY, true, true);
				this.NextPage(ref this.startLine);
				this.page++;
				this.pageIndex++;
				e.HasMorePages = (this.page < this.pages);
			}
			finally
			{
				painter.EndPaint();
			}
		}
		public EditorPrintDocument(Printing printing, PrinterSettings settings)
		{
			this.printing = printing;
			base.PrinterSettings = settings;
		}
		public void Init(CodeEditor edit)
		{
			this.Init(edit, false);
		}
		public virtual void Init(CodeEditor edit, bool calcPages)
		{
			base.PrinterSettings.MinimumPage = 1;
			base.PrinterSettings.FromPage = Math.Max(base.PrinterSettings.FromPage, 1);
			base.PrinterSettings.ToPage = Math.Max(base.PrinterSettings.ToPage, 1);
			this.CreatePrintEdit(edit);
			if (calcPages)
			{
				base.PrinterSettings.ToPage = Math.Max(this.GetPagesCount(), 1);
			}
			this.printing.OnInitialized();
		}
	}
}
